package com.preViewPrint
{
	import flash.display.Sprite;
	import flash.geom.Rectangle;
	import flash.printing.PrintJob;
	import flash.printing.PrintJobOrientation;
	
	import mx.core.UIComponent;
	
	public class PrintManager
	{
		public function PrintManager()
		{
		}
		
		public function print(document:IPrintableDocument, parent:UIComponent = null):Boolean
		{
			var printJob:PrintJob = new PrintJob();
			
			if (parent != null)
				parent.addChild(document.displayObject());
			
			var printed:Boolean = printInternal(document, printJob);           
			
			if (parent != null)
				parent.removeChild(document.displayObject());
			
			return printed;
		}
		
		private function unscaleDocument(document:IPrintableDocument):void
		{
			document.scaleX = 1;
			document.scaleY = 1;
			document.validateNow();
		}
		
		private function rotateDocumentForPaperOrientation(document:IPrintableDocument, printJob:PrintJob):void
		{
			var pageIsLandscape:Boolean = (printJob.orientation == PrintJobOrientation.LANDSCAPE);
			var desiredPageIsLandscape:Boolean = (document.desiredWidth > document.desiredHeight);
			
			document.x = 0;
			document.y = 0;
			
			var scaleFactor:Number;
			
			if (pageIsLandscape != desiredPageIsLandscape)
			{
				scaleFactor = scaleFactorForDocument(
					document.desiredHeight,
					document.desiredWidth,
					printJob.pageWidth,
					printJob.pageHeight
				);
				document.rotation = 90;
			}
			else
			{
				scaleFactor = scaleFactorForDocument(
					document.desiredWidth,
					document.desiredHeight,
					printJob.pageWidth,
					printJob.pageHeight
				);
			}
			document.scaleX = scaleFactor;
			document.scaleY = scaleFactor;
			document.validateNow();
		}
		
		private function scaleFactorForDocument(docWidth:Number, docHeight:Number, jobWidth:Number, jobHeight:Number):Number
		{
			var jobRatio:Number = jobWidth / jobHeight;
			var docRatio:Number = docWidth / docHeight;
			
			var jobLimit:Number = (docRatio <= jobRatio) ? jobHeight : jobWidth;
			var docLimit:Number = (docRatio <= jobRatio) ? docHeight : docWidth;
			
			var scaleFactor:Number = jobLimit / docLimit;
			
			return scaleFactor;
		}
		
		private function printPage(document:IPrintableDocument, printJob:PrintJob):void
		{
			var width:Number = document.desiredWidth;
			var height:Number = document.desiredHeight;
			var page:Sprite = Sprite(document);
			var printableArea:Rectangle = new Rectangle(0, 0, width, height);
			printJob.addPage(page, printableArea);
		}
		
		public function printInternal(document:IPrintableDocument, printJob:PrintJob):Boolean
		{
			if (printJob.start() == false) {
				return false;
			}
			document.moveToFirstPage();
			unscaleDocument(document);
			
			rotateDocumentForPaperOrientation(document, printJob);
			
			printPage(document, printJob);
			while(document.validNextPage)
			{
				document.nextPage();
				printPage(document, printJob);
			}
			
			printJob.send();
			return true;
		}
	}

}